package good.idea.data.excel.read.template;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFPrintSetup;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import good.idea.data.excel.context.ExcelTemplateContext;
import good.idea.data.excel.entity.CellEntity;
import good.idea.data.excel.entity.RowEntity;
import good.idea.data.excel.entity.TemplateElement;
import good.idea.data.excel.entity.TemplateTag;
import good.idea.data.utils.LangUtils;
import good.idea.data.utils.RefUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author chm
 */
public class TemplateHelper {


    public static final Map<String, String> TEMP_FILE_NAME_MAP = new HashMap<>();

    private static final String EXCEL_ELEMENT_START_TAG = "<for";
    private static final String EXCEL_ELEMENT_END_TAG = "</for";


    /**
     * 解析模板内容
     *
     * @param context
     * @param rowEntity
     * @param index
     */
    public static void parserTemplateTag(ExcelTemplateContext context, RowEntity rowEntity, int index) {
        String startTagName = EXCEL_ELEMENT_START_TAG;
        String end = EXCEL_ELEMENT_END_TAG;
        StringBuilder sb = new StringBuilder();
        XSSFRow thisRow = rowEntity.getThisRow();
        int columnNum = thisRow.getPhysicalNumberOfCells();
        int cellTagFlag = 0;
        CellEntity startCell = null;
        CellEntity endCell = null;
        TemplateElement element = new TemplateElement();
        for (int c = 0; c < columnNum; c++) {
            XSSFCell cell = thisRow.getCell(c);
            if (cell != null) {
                int[] indexs = getMergedRegionIndex(context.getActivitySheet(), index, c);
                CellEntity cellEntity = new CellEntity();
                cellEntity.setThisCell(cell);
                boolean ic = checkCosIndex(rowEntity, indexs);
                if (ic) {
                    cellEntity.setCosIndex(indexs);
                }
                rowEntity.getCellEntities().add(cellEntity);
                String val = String.valueOf(cell.toString());
                sb.append(val);

                if (val.indexOf(startTagName) > -1) {
                    //列的遍历功能，缺省
                    cellTagFlag++;
                    TemplateTag templateTag = addTemplateTag(context, null);
                    context.setActiveTemplateTag(templateTag);
                    setTemplateTagStartIndex(templateTag, index, c);
                    dualTemplateTagAttr(val, templateTag);
                    rowEntity.setTemplateTagFlag(1);
                    rowEntity.setTemplateTag(templateTag);
                    cellEntity.setTemplateTagFlag(1);
                    cellEntity.setTemplateTag(templateTag);
                    startCell = cellEntity;
                }
                if (val.indexOf(end) > -1) {
                    //列的遍历功能，缺省
                    endCell = cellEntity;
                    if (startCell != null) {


                    }
                    TemplateTag templateTag = TemplateHelper.setTemplateTagEndIndex(context.getActiveTemplateTag(), index, c);
                    if (templateTag.getParent() != null) {
                        context.setActiveTemplateTag(templateTag.getParent());
                    }
                    cellEntity.setTemplateTagFlag(2);
                    cellTagFlag++;
                }
            }
        }

        if (cellTagFlag > 1) {
            return;
        }
        String str = sb.toString().trim();
        if (str.startsWith(startTagName) && cellTagFlag == 0) {
            TemplateTag templateTag = addTemplateTag(context, null);
            context.setActiveTemplateTag(templateTag);
            setTemplateTagStartIndex(templateTag, index, 0);
            dualTemplateTagAttr(str, templateTag);
            rowEntity.setTemplateTagFlag(1);
            rowEntity.setTemplateTag(templateTag);
            rowEntity.setTemplateElement(element);
        }

        if (str.startsWith(end)) {
            //寻找上一个组成未闭合的标签
            List<TemplateTag> templateTags = context.getActiveTemplateTags();
            for (int i = templateTags.size() - 1; i >= 0; i--) {
                TemplateTag templateTag = templateTags.get(i);
                if ("start".equals(templateTag.getTagFlag()) && templateTag.getTagEndIndex() == 0) {
                    templateTag.setTagEndIndex(index);
                    break;
                }
            }
            rowEntity.setTemplateElementFlag(2);
        }
    }

    /**
     * 读取最后开口的模板语言标签
     *
     * @param items
     * @param templateTag
     * @return
     */
    public static TemplateTag getLastOpenTemplateTag(List<TemplateTag> items, TemplateTag templateTag) {
        if (LangUtils.isNotEmpty(items)) {
            for (TemplateTag item : items) {
                if (!"end".equals(item.getTagFlag())) {
                    return getLastOpenTemplateTag(item.getChildren(), item);
                }
            }
        }
        return templateTag;
    }


    /**
     * 读取标签的内容，绑定相关参数
     *
     * @param str
     * @param templateTag
     */
    public static void dualTemplateTagAttr(String str, TemplateTag templateTag) {
        String[] arrs = str.split(" ");
        for (int i = 0; i < arrs.length; i++) {
            String s = arrs[i];
            String[] vs = s.split("=");
            if (vs.length == 2) {
                String name = vs[0];
                String val = vs[1];
                if (val.length() > 2) {
                    val = val.substring(1, val.length() - 1);
                }
                RefUtils.setFieldValue(templateTag, name, val);
            }
        }

    }

    public static TemplateTag setTemplateTagStartIndex(TemplateTag templateTag, int rowIndex, int cellIndex) {
        templateTag.setStartRowIndex(rowIndex);
        templateTag.setStartCellIndex(cellIndex);
        initTemplateTagFlag(templateTag);
        return templateTag;
    }


    public static TemplateTag setTemplateTagEndIndex(TemplateTag templateTag, int rowIndex, int cellIndex) {
        templateTag.setEndRowIndex(rowIndex);
        templateTag.setEndCellIndex(cellIndex);
        initTemplateTagFlag(templateTag);
        return templateTag;
    }

    public static void initTemplateTagFlag(TemplateTag templateTag) {
        if (templateTag.getTagFlag() == null) {
            templateTag.setTagFlag("start");
        } else {
            templateTag.setTagFlag("end");
        }
    }

    /**
     * 增加模板语言标签
     *
     * @param templateContext
     * @param templateTag
     * @return
     */
    public static TemplateTag addTemplateTag(ExcelTemplateContext templateContext, TemplateTag templateTag) {
        if (templateTag == null) {
            templateTag = new TemplateTag();
            TemplateTag parent = getLastOpenTemplateTag(templateContext.getActiveTemplateTags(), null);
            templateTag.setParent(parent);
        }
        boolean flag = true;
        List<TemplateTag> templateTags = templateContext.getActiveTemplateTags();
        for (TemplateTag tag : templateTags) {
            if (templateTag == tag) {
                flag = false;
                break;
            }
        }
        if (flag) {
            templateTags.add(templateTag);
        }
        return templateTag;
    }

    /**
     * 检查当前单元格是否为：多行多列合并单元格
     *
     * @param rowEntity
     * @param indexs
     * @return
     */
    public static boolean checkCosIndex(RowEntity rowEntity, int[] indexs) {
        boolean flag = true;
        if (indexs != null) {
            int vst = indexs[0];
            int ved = indexs[1];
            int st = indexs[2];
            int ed = indexs[3];
            List<CellEntity> cellEntities = rowEntity.getCellEntities();
            for (CellEntity cellEntity : cellEntities) {
                int[] idxs = cellEntity.getCosIndex();
                if (idxs != null) {
                    int vstart = idxs[0];
                    int vend = idxs[1];
                    int start = idxs[2];
                    int end = idxs[3];
                    if (st >= start && ed <= end) {
                        return false;
                    }
                }
            }
            rowEntity.getMergedIndexs().add(indexs);

        } else {
            flag = false;
        }

        return flag;
    }


    /**
     * 获取合并的单元格索引数组
     *
     * @param sheet
     * @param row
     * @param column
     * @return
     */
    private static int[] getMergedRegionIndex(Sheet sheet, int row, int column) {
        int[] indexs = null;
        int sheetMergeCount = sheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (row >= firstRow && row <= lastRow) {
                if (column >= firstColumn && column <= lastColumn) {
                    indexs = new int[]{firstRow, row, column, lastColumn};
                }
            }
        }
        return indexs;

    }

    /**
     * 将当前工作页内容清空
     * 保留基本的格式设置以及数据公式等内容
     *
     * @param context
     */
    public static void clearSheetContent(ExcelTemplateContext context) {
        removeSheetAllRows(context);
        removeSheetAllRows(context);
        removeSheetAllRows(context);
        removeSheetAgainMerged(context);
    }


    /**
     * 删除合并的单元格
     *
     * @param context
     */
    public static void removeSheetAgainMerged(ExcelTemplateContext context) {
        List<List<CellEntity>> cellEntities = context.getAllCellEntitys();


        for (int i = 0; i < cellEntities.size(); i++) {
            List<CellEntity> ces = cellEntities.get(i);
            int cc = 0;
            for (int j = ces.size() - 1; j >= 0; j--) {
                cc++;
                CellEntity ce = ces.get(j);
                int[] indexs = ce.getCosIndex();
                if (indexs != null) {
                    int vst = indexs[0];
                    int ved = indexs[1];
                    int st = indexs[2];
                    int ed = indexs[3];
                    for (int k = 0; k < ces.size() - cc; k++) {
                        CellEntity col = ces.get(k);
                        int[] idxs = col.getCosIndex();
                        if (idxs != null) {
                            int vstart = idxs[0];
                            int vend = idxs[1];
                            int start = idxs[2];
                            int end = idxs[3];
                            if (st == start && ed == end && vst <= vstart && ved >= vend) {
                                col.setCosIndex(null);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 删除所有的单元格内容
     *
     * @param context
     */
    public static void removeSheetAllRows(ExcelTemplateContext context) {
        List<RowEntity> rowEntities = context.getActiveRowEntities();
        Sheet activitySheet = context.getActivitySheet();
        for (int i = rowEntities.size() - 1; i > 0; i--) {
            RowEntity cls = rowEntities.get(i);
            Row row = activitySheet.getRow(i);
            if (row != null) {
                activitySheet.removeRow(row);
            }
        }

        try {
            int numMergedRegions = activitySheet.getNumMergedRegions();
            for (int i = 0; i <= numMergedRegions; i++) {
                activitySheet.removeMergedRegion(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        Row row = activitySheet.getRow(0);
        if (row != null) {
            if (row.getCell(0) != null) {
                row.getCell(0).setCellValue("");
            }
            activitySheet.removeRow(row);
        }
    }

    /**
     * 复制打印样式
     * 依稀记得之前的版本克隆是没有问题的
     * 现在克隆要手动复制打印的设置
     * @param srcSheet
     * @param targetSheet
     */
    public static void copyPrintSetup(XSSFSheet srcSheet, XSSFSheet targetSheet) {
        XSSFPrintSetup printSetup1 = srcSheet.getPrintSetup();
        XSSFPrintSetup printSetup2 = targetSheet.getPrintSetup();

        printSetup2.setBottomMargin(printSetup1.getBottomMargin());
        printSetup2.setCopies(printSetup1.getCopies());
        printSetup2.setDraft(printSetup1.getDraft());
        printSetup2.setFitHeight(printSetup1.getFitHeight());
        printSetup2.setFitWidth(printSetup1.getFitWidth());
        printSetup2.setHeaderMargin(printSetup1.getHeaderMargin());
        printSetup2.setFooterMargin(printSetup1.getFooterMargin());
        printSetup2.setHResolution(printSetup1.getHResolution());
        printSetup2.setLandscape(printSetup1.getLandscape());
        printSetup2.setLeftMargin(printSetup1.getLeftMargin());
        printSetup2.setNoColor(printSetup1.getNoColor());
        printSetup2.setNoOrientation(printSetup1.getNoOrientation());
        printSetup2.setNotes(printSetup1.getNotes());
        printSetup2.setLeftToRight(printSetup1.getLeftToRight());
        printSetup2.setOrientation(printSetup1.getOrientation());
        printSetup2.setPageOrder(printSetup1.getPageOrder());
        printSetup2.setPageStart(printSetup1.getPageStart());
        printSetup2.setPaperSize(printSetup1.getPaperSize());
        printSetup2.setRightMargin(printSetup1.getRightMargin());
        printSetup2.setScale(printSetup1.getScale());
        printSetup2.setTopMargin(printSetup1.getTopMargin());
        printSetup2.setUsePage(printSetup1.getUsePage());
        printSetup2.setValidSettings(printSetup1.getValidSettings());
        printSetup2.setVResolution(printSetup1.getHResolution());

    }

}
